1 // ----------------------------------------------------------------------------
2 // <copyright file=
"PhotonConverter.cs" company="Exit Games GmbH">
3 // PhotonNetwork Framework
for Unity - Copyright (C) 2011 Exit Games GmbH
4 // </copyright>
5 // <summary>
6 // Script to convert a Unity Networking project to PhotonNetwork.
7 // </summary>
8 // <author>developer@exitgames.com</author>
9 // ----------------------------------------------------------------------------

10 using
UnityEngine;
11 using
UnityEditor;
12 using
System.Collections.Generic;
13 using
System.IO;
14 using
System.Text.RegularExpressions;
15
16 public
class PhotonConverter : Photon.MonoBehaviour
17 {
18     
public static void RunConversion()
19     {
20         
//Ask if user has made a backup.
21         
int option = EditorUtility.DisplayDialogComplex("Conversion", "Attempt automatic conversion from Unity Networking to Photon Unity Networking \"PUN\"?", "Yes", "No!", "Pick Script Folder");
22         
switch (option)
23         {
24             
case 0:
25                 
break;
26             
case 1:
27                 
return;
28             
case 2:
29                 PickFolderAndConvertScripts();
30                 
return;
31             
default:
32                 
return;
33         }
34
35         
//REAAAALY?
36         
bool result = EditorUtility.DisplayDialog("Conversion", "Disclaimer: The code conversion feature is quite crude, but should do it's job well (see the sourcecode). A backup is therefore strongly recommended!", "Yes, I've made a backup: GO", "Abort");
37         
if (!result)
38         {
39             
return;
40         }
41         Output(EditorApplication.timeSinceStartup +
" Started conversion of Unity networking -> Photon");
42
43         
//Ask to save current scene (optional)
44         EditorApplication.SaveCurrentSceneIfUserWantsTo();
45
46         EditorUtility.DisplayProgressBar(
"Converting..", "Starting.", 0);
47
48         
//Convert NetworkViews to PhotonViews in Project prefabs
49         
//Ask the user if we can move all prefabs to a resources folder
50         
bool movePrefabs = EditorUtility.DisplayDialog("Conversion", "Can all prefabs that use a PhotonView be moved to a Resources/ folder? You need this if you use Network.Instantiate.", "Yes", "No");
51
52
53         
string[] prefabs = Directory.GetFiles("Assets/", "*.prefab", SearchOption.AllDirectories);
54         
foreach (string prefab in prefabs)
55         {
56             EditorUtility.DisplayProgressBar(
"Converting..", "Object:" + prefab, 0.6f);
57
58             Object[] objs = (Object[])AssetDatabase.LoadAllAssetsAtPath(prefab);
59             
int converted = 0;
60             
foreach (Object obj in objs)
61             {
62                 
if (obj != null && obj.GetType() == typeof(GameObject))
63                     converted += ConvertNetworkView(((GameObject)obj).GetComponents<NetworkView>(),
false);
64             }
65             
if (movePrefabs && converted > 0)
66             {
67                 
//This prefab needs to be under the root of a Resources folder!
68                 
string path = prefab.Replace("\\", "/");
69                 
int lastSlash = path.LastIndexOf("/");
70                 
int resourcesIndex = path.LastIndexOf("/Resources/");
71                 
if (resourcesIndex != lastSlash - 10)
72                 {
73                     
if (path.Contains("/Resources/"))
74                     {
75                         Debug.LogWarning(
"Warning, prefab [" + prefab + "] was already in a resources folder. But has been placed in the root of another one!");
76                     }
77                     
//This prefab NEEDS to be placed under a resources folder
78                     
string resourcesFolder = path.Substring(0, lastSlash) + "/Resources/";
79                     EnsureFolder(resourcesFolder);
80                     
string newPath = resourcesFolder + path.Substring(lastSlash + 1);
81                     
string error = AssetDatabase.MoveAsset(prefab, newPath);
82                     
if (error != "")
83                         Debug.LogError(error);
84                     Output(
"Fixed prefab [" + prefab + "] by moving it into a resources folder.");
85                 }
86             }
87         }
88
89         
//Convert NetworkViews to PhotonViews in scenes
90         
string[] sceneFiles = Directory.GetFiles("Assets/", "*.unity", SearchOption.AllDirectories);
91         
foreach (string sceneName in sceneFiles)
92         {
93             EditorApplication.OpenScene(sceneName);
94             EditorUtility.DisplayProgressBar(
"Converting..", "Scene:" + sceneName, 0.2f);
95
96             
int converted2 = ConvertNetworkView((NetworkView[])GameObject.FindObjectsOfType(typeof(NetworkView)), true);
97             
if (converted2 > 0)
98             {
99                 
//This will correct all prefabs: The prefabs have gotten new components, but the correct ID's were lost in this case
100                 PhotonViewHandler.HierarchyChange();
//TODO: most likely this is triggered on change or on save
101
102                 Output(
"Replaced " + converted2 + " NetworkViews with PhotonViews in scene: " + sceneName);
103                 EditorApplication.SaveScene(EditorApplication.currentScene);
104             }
105
106         }
107
108         
//Convert C#/JS scripts (API stuff)
109         List<
string> scripts = GetScriptsInFolder("Assets");
110
111         EditorUtility.DisplayProgressBar(
"Converting..", "Scripts..", 0.9f);
112         ConvertScripts(scripts);
113
114         Output(EditorApplication.timeSinceStartup +
" Completed conversion!");
115         EditorUtility.ClearProgressBar();
116
117         EditorUtility.DisplayDialog(
"Completed the conversion", "Don't forget to add \"PhotonNetwork.ConnectWithDefaultSettings();\" to connect to the Photon server before using any multiplayer functionality.", "OK");
118     }
119
120     
public static void PickFolderAndConvertScripts()
121     {
122         
string folderPath = EditorUtility.OpenFolderPanel("Pick source folder to convert", Directory.GetCurrentDirectory(), "");
123         
if (string.IsNullOrEmpty(folderPath))
124         {
125             EditorUtility.DisplayDialog(
"Script Conversion", "No folder was selected. No files were changed. Please start over.", "Ok.");
126             
return;
127         }
128
129         
bool result = EditorUtility.DisplayDialog("Script Conversion", "Scripts in this folder will be modified:\n\n" + folderPath + "\n\nMake sure you have backups of these scripts.\nConversion is not guaranteed to work!", "Backup done. Go!", "Abort");
130         
if (!result)
131         {
132             
return;
133         }
134
135         List<
string> scripts = GetScriptsInFolder(folderPath);
136         ConvertScripts(scripts);
137
138         EditorUtility.DisplayDialog(
"Script Conversion", "Scripts are now converted to PUN.\n\nYou will need to update\n- scenes\n- components\n- prefabs and\n- add \"PhotonNetwork.ConnectWithDefaultSettings();\"", "Ok");
139     }
140
141
142     
public static List<string> GetScriptsInFolder(string folder)
143     {
144         List<
string> scripts = new List<string>();
145
146         
try
147         {
148             scripts.AddRange(Directory.GetFiles(folder,
"*.cs", SearchOption.AllDirectories));
149             scripts.AddRange(Directory.GetFiles(folder,
"*.js", SearchOption.AllDirectories));
150             scripts.AddRange(Directory.GetFiles(folder,
"*.boo", SearchOption.AllDirectories));
151         }
152         
catch (System.Exception ex)
153         {
154             Debug.Log(
"Getting script list from folder " + folder + " failed. Exception:\n" + ex.ToString());
155         }
156
157         
return scripts;
158     }
159
160     
static void ConvertScripts(List<string> scriptPathList)
161     {
162         
bool ignoreWarningIsLogged = false;
163
164         
foreach (string script in scriptPathList)
165         {
166             
if (script.Contains("PhotonNetwork")) //Don't convert this file (and others)
167             {
168                 
if (!ignoreWarningIsLogged)
169                 {
170                     ignoreWarningIsLogged =
true;
171                     Debug.LogWarning(
"Conversion to PUN ignores all files with \"PhotonNetwork\" in their file-path.\nCheck: " + script);
172                 }
173                 
continue;
174             }
175             
if (script.Contains("Image Effects"))
176             {
177                 
continue;
178             }
179
180             ConvertToPhotonAPI(script);
181         }
182
183         
foreach (string script in scriptPathList)
184         {
185             AssetDatabase.ImportAsset(script, ImportAssetOptions.ForceUpdate);
186         }
187     }
188
189     
static void ConvertToPhotonAPI(string file)
190     {
191         
string text = File.ReadAllText(file);
192
193         
bool isJS = file.Contains(".js");
194
195         file = file.Replace(
"\\", "/"); // Get Class name for JS
196         
string className = file.Substring(file.LastIndexOf("/")+1);
197         className = className.Substring(
0, className.IndexOf("."));
198
199
200         
//REGEXP STUFF
201         
//Valid are: Space { } , /n /r
202         
//string NOT_VAR = @"([^A-Za-z0-9_\[\]\.]+)";
203         
string NOT_VAR_WITH_DOT = @"([^A-Za-z0-9_]+)";
204
205         
//string VAR_NONARRAY = @"[^A-Za-z0-9_]";
206
207
208         
//NetworkView
209         {
210             text = PregReplace(text, NOT_VAR_WITH_DOT +
"NetworkView" + NOT_VAR_WITH_DOT, "$1PhotonView$2");
211             text = PregReplace(text, NOT_VAR_WITH_DOT +
"networkView" + NOT_VAR_WITH_DOT, "$1photonView$2");
212             text = PregReplace(text, NOT_VAR_WITH_DOT +
"stateSynchronization" + NOT_VAR_WITH_DOT, "$1synchronization$2");
213             text = PregReplace(text, NOT_VAR_WITH_DOT +
"NetworkStateSynchronization" + NOT_VAR_WITH_DOT, "$1ViewSynchronization$2"); // map Unity enum to ours
214             
//.RPC
215             text = PregReplace(text, NOT_VAR_WITH_DOT +
"RPCMode.Server" + NOT_VAR_WITH_DOT, "$1PhotonTargets.MasterClient$2");
216             text = PregReplace(text, NOT_VAR_WITH_DOT +
"RPCMode" + NOT_VAR_WITH_DOT, "$1PhotonTargets$2");
217         }
218
219         
//NetworkMessageInfo: 100%
220         {
221             text = PregReplace(text, NOT_VAR_WITH_DOT +
"NetworkMessageInfo" + NOT_VAR_WITH_DOT, "$1PhotonMessageInfo$2");
222             text = PregReplace(text, NOT_VAR_WITH_DOT +
"networkView" + NOT_VAR_WITH_DOT, "$1photonView$2");
223         }
224
225         
//NetworkViewID:
226         {
227             text = PregReplace(text, NOT_VAR_WITH_DOT +
"NetworkViewID" + NOT_VAR_WITH_DOT, "$1int$2"); //We simply use an int
228         }
229
230         
//NetworkPlayer
231         {
232             text = PregReplace(text, NOT_VAR_WITH_DOT +
"NetworkPlayer" + NOT_VAR_WITH_DOT, "$1PhotonPlayer$2");
233         }
234
235         
//Network
236         {
237             
//Monobehaviour callbacks
238             {
239                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"OnPlayerConnected" + NOT_VAR_WITH_DOT, "$1OnPhotonPlayerConnected$2");
240                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"OnPlayerDisconnected" + NOT_VAR_WITH_DOT, "$1OnPhotonPlayerDisconnected$2");
241                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"OnNetworkInstantiate" + NOT_VAR_WITH_DOT, "$1OnPhotonInstantiate$2");
242                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"OnSerializeNetworkView" + NOT_VAR_WITH_DOT, "$1OnPhotonSerializeView$2");
243                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"BitStream" + NOT_VAR_WITH_DOT, "$1PhotonStream$2");
244
245                 
//Not completely the same meaning
246                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"OnServerInitialized" + NOT_VAR_WITH_DOT, "$1OnCreatedRoom$2");
247                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"OnConnectedToServer" + NOT_VAR_WITH_DOT, "$1OnJoinedRoom$2");
248
249                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"OnFailedToConnectToMasterServer" + NOT_VAR_WITH_DOT, "$1OnFailedToConnectToPhoton$2");
250                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"OnFailedToConnect" + NOT_VAR_WITH_DOT, "$1OnFailedToConnect_OBSELETE$2");
251             }
252
253             
//Variables
254             {
255
256                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"Network.connections" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.playerList$2");
257                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"Network.isServer" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.isMasterClient$2");
258                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"Network.isClient" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.isNonMasterClientInRoom$2");
259
260                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"NetworkPeerType" + NOT_VAR_WITH_DOT, "$1ConnectionState$2");
261                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"Network.peerType" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.connectionState$2");
262                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"ConnectionState.Server" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.isMasterClient$2");
263                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"ConnectionState.Client" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.isNonMasterClientInRoom$2");
264                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"PhotonNetwork.playerList.Length" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.playerList.Count$2");
265
266                 
/*DROPPED:
267                     minimumAllocatableViewIDs
268                     natFacilitatorIP
is dropped
269                     natFacilitatorPort
is dropped
270                     connectionTesterIP
271                     connectionTesterPort
272                     proxyIP
273                     proxyPort
274                     useProxy
275                     proxyPassword
276                  */

277             }
278
279             
//Methods
280             {
281                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"Network.InitializeServer" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.CreateRoom$2");
282                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"Network.Connect" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.JoinRoom$2");
283                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"Network.GetAveragePing" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.GetPing$2");
284                 text = PregReplace(text, NOT_VAR_WITH_DOT +
"Network.GetLastPing" + NOT_VAR_WITH_DOT, "$1PhotonNetwork.GetPing$2");
285                 
/*DROPPED:
286                     TestConnection
287                     TestConnectionNAT
288                     HavePublicAddress
289                 */

290             }
291
292             
//Overall
293             text = PregReplace(text, NOT_VAR_WITH_DOT +
"Network" + NOT_VAR_WITH_DOT, "$1PhotonNetwork$2");
294
295
296         
//Changed methods
297              
string ignoreMe = @"([A-Za-z0-9_\[\]\(\) ]+)";
298
299          text = PregReplace(text, NOT_VAR_WITH_DOT +
"PhotonNetwork.GetPing\\(" + ignoreMe+"\\);", "$1PhotonNetwork.GetPing();");
300         text = PregReplace(text, NOT_VAR_WITH_DOT +
"PhotonNetwork.CloseConnection\\(" + ignoreMe+","+ignoreMe+"\\);", "$1PhotonNetwork.CloseConnection($2);");
301
302         }
303
304         
//General
305         {
306             
if (text.Contains("Photon")) //Only use the PhotonMonoBehaviour if we use photonView and friends.
307             {
308                 
if (isJS)//JS
309                 {
310                     
if (text.Contains("extends MonoBehaviour"))
311                         text = PregReplace(text,
"extends MonoBehaviour", "extends Photon.MonoBehaviour");
312                     
else
313                         text =
"class " + className + " extends Photon.MonoBehaviour {\n" + text + "\n}";
314                 }
315                 
else //C#
316                     text = PregReplace(text,
": MonoBehaviour", ": Photon.MonoBehaviour");
317             }
318         }
319
320         File.WriteAllText(file, text);
321     }
322
323     
static string PregReplace(string input, string[] pattern, string[] replacements)
324     {
325         
if (replacements.Length != pattern.Length)
326             Debug.LogError(
"Replacement and Pattern Arrays must be balanced");
327
328         
for (var i = 0; i < pattern.Length; i++)
329         {
330             input = Regex.Replace(input, pattern[i], replacements[i]);
331         }
332
333         
return input;
334     }
335     
static string PregReplace(string input, string pattern, string replacement)
336     {
337         
return Regex.Replace(input, pattern, replacement);
338
339     }
340
341     
static void EnsureFolder(string path)
342     {
343         
if (!Directory.Exists(path))
344         {
345             Directory.CreateDirectory(path);
346             AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
347             AssetDatabase.Refresh();
348         }
349     }
350
351     
static int ConvertNetworkView(NetworkView[] netViews, bool isScene)
352     {
353         
for (int i = netViews.Length - 1; i >= 0; i--)
354         {
355             NetworkView netView = netViews[i];
356             PhotonView view = netView.gameObject.AddComponent<PhotonView>();
357             
if (isScene)
358             {
359                 
//Get scene ID
360                 
string str = netView.viewID.ToString().Replace("SceneID: ", "");
361                 
int firstSpace = str.IndexOf(" ");
362                 str = str.Substring(
0, firstSpace);
363                 
int oldViewID = int.Parse(str);
364
365                 view.viewID = oldViewID;
366                 EditorUtility.SetDirty(view);
367                 EditorUtility.SetDirty(view.gameObject);
368             }
369             view.observed = netView.observed;
370             
if (netView.stateSynchronization == NetworkStateSynchronization.Unreliable)
371             {
372                 view.synchronization = ViewSynchronization.Unreliable;
373             }
374             
else if (netView.stateSynchronization == NetworkStateSynchronization.ReliableDeltaCompressed)
375             {
376                 view.synchronization = ViewSynchronization.ReliableDeltaCompressed;
377             }
378             
else
379             {
380                 view.synchronization = ViewSynchronization.Off;
381             }
382             DestroyImmediate(netView,
true);
383         }
384         AssetDatabase.Refresh();
385         AssetDatabase.SaveAssets();
386
387         
return netViews.Length;
388     }
389
390     
static void Output(string str)
391     {
392         Debug.Log(((
int)EditorApplication.timeSinceStartup) + " " + str);
393     }
394
395     
static void ConversionError(string file, string str)
396     {
397         Debug.LogError(
"Scrip conversion[" + file + "]: " + str);
398     }
399
400 }


----------------------------------------------------------------------------

PhotonNetwork Framework for Unity - Copyright (C) 2011 Exit Games GmbH

Script to convert a Unity Networking project to PhotonNetwork.

developer@exitgames.com

----------------------------------------------------------------------------

Ask if user has made a backup.

REAAAALY?

Ask to save current scene (optional)

Convert NetworkViews to PhotonViews in Project prefabs

Ask the user if we can move all prefabs to a resources folder

This prefab needs to be under the root of a Resources folder!

This prefab NEEDS to be placed under a resources folder

Convert NetworkViews to PhotonViews in scenes

This will correct all prefabs: The prefabs have gotten new components, but the correct ID's were lost in this case

PhotonViewHandler.HierarchyChange(); TODO: most likely this is triggered on change or on save

Convert C#JS scripts (API stuff)

if (script.Contains("PhotonNetwork")) Don't convert this file (and others)

file = file.Replace("\\", ""); Get Class name for JS

REGEXP STUFF

Valid are: Space { } , n r

string NOT_VAR = @"([^A-Za-z0-9_\[\]\.]+)";

string VAR_NONARRAY = @"[^A-Za-z0-9_]";

NetworkView

text = PregReplace(text, NOT_VAR_WITH_DOT + "NetworkStateSynchronization" + NOT_VAR_WITH_DOT, "$1ViewSynchronization$2"); map Unity enum to ours

.RPC

NetworkMessageInfo: 100%

NetworkViewID:

text = PregReplace(text, NOT_VAR_WITH_DOT + "NetworkViewID" + NOT_VAR_WITH_DOT, "$1int$2"); We simply use an int

NetworkPlayer

Network

Monobehaviour callbacks

Not completely the same meaning

Variables

Methods

Overall

Changed methods

General

if (text.Contains("Photon")) Only use the PhotonMonoBehaviour if we use photonView and friends.

if (isJS)JS

else C#

Get scene ID




Trò chơi Tic-Tac-Toe, game đánh caro full source code 53.569 lượt xem

Gõ tìm kiếm nhanh...